namespace ui {
	// 主要用于动态的销毁资源！like westBmp
	export class BaseImage extends eui.Image {
		mUrl: string;

		mCache: string;

		refresh(source: string): void {}

		override $onAddToStage(stage: egret.Stage, nestLevel: number): void {
			super.$onAddToStage(stage, nestLevel);
			if (this.mCache) {
				this.refresh(this.mCache);
				this.mCache = null;
			}
		}

		release(): void {
			if (this.mUrl) {
				this.mCache = this.mUrl;
				this.refresh(null);
			}
		}

		override $onRemoveFromStage(): void {
			super.$onRemoveFromStage();
			this.release();
		}
	}

	export class Image extends BaseImage {
		override refresh(source: string): void {
			this.url(source);
		}

		tag = 'ui.Image';

		async url(newUrl: string): Promise<void> {
			if (this.mUrl === newUrl) {
				return;
			}
			if (this.mUrl) {
				ResMgr.ins().unref(this.mUrl, this.tag);
				this.mUrl = null;
			}

			this.mUrl = newUrl;
			this.mCache = null;
			if (newUrl) {
				ResMgr.ins().ref(this.mUrl, this.tag);
				const tex = await loadTextureByUrl(newUrl);
				if (tex) {
					this.source = tex;
				}
			}
		}
	}
	// ui上的movieclip!
	// 如果ui移除了场景，自动删除！
	// 派生Animation封装mc 是为了放在编辑器里可以看到
	export class Animation extends eui.Component implements eui.UIComponent {
		rect: eui.Rect;

		mc: WestMC;

		// byUrl = true;
		release(): void {
			if (this.mc) {
				this.removeChild(this.mc);
				this.mc.release();
				this.mc = null;
			}
		}

		override $onAddToStage(stage: egret.Stage, nestLevel: number): void {
			super.$onAddToStage(stage, nestLevel);
			if (!this.stage) {
				return;
			}
			if (this.mc || !this.file) {
				return;
			}
			// console.log("restore when onAddToStage")
			this.updateAnimation(true);
		}

		override $onRemoveFromStage(): void {
			super.$onRemoveFromStage();
			this.release();
		}

		// 使用property  EXMLConfig.prototype.getPropertyType 无法识别！

		file: string = '';

		public setFile(v: string) {
			this.file = v;
			if (this.file) {
				this.updateAnimation();
			}
		}

		private _dir: string;

		public get dir(): string {
			return this._dir;
		}

		public set dir(v: string) {
			this._dir = v;
			if (this.file) {
				this.updateAnimation();
			}
		}

		protected override childrenCreated(): void {
			super.childrenCreated();
			if (this.rect) {
				this.rect.visible = false;
			}
		}

		public setAnimation(file: string, dir?: string): Promise<void> {
			this.file = file;
			this._dir = dir;
			return this.updateAnimation();
		}

		public setCharAnimation(id: number, ani: string, dir?: string): Promise<void> {
			this.file = `${id}_${ani}`;
			this.dir = dir;
			return this.updateAnimation();
		}

		loading = false;

		public async updateAnimation(checkloading = false): Promise<void> {
			if (checkloading && this.loading) {
				return;
			}
			if (!this.stage) {
				return;
			}

			const { file } = this;
			const { dir } = this;

			if (this.rect) {
				this.rect.visible = false;
			}

			// console.log("this.loading ;",this.loading)
			this.loading = true;
			const mc = await poolLoadMcAsyncByUrl('ui.Animation', file, dir);
			// console.log("this.loading = false;")
			this.loading = false;
			if (!mc) {
				return;
			}

			if (!this.stage) {
				mc.release();
				return;
			}

			this.release();

			this.addChild(mc);
			// ResMgr.ins().refMC(this.file)
			// mc.play(-1);
			this.mc = mc;

			this.onLoadedMC();
		}

		onLoadedMC(): void {
			if (this.playtimes) {
				if (this.goto >= 0) {
					this.mc.gotoAndPlay(this.goto, this.playtimes);
				} else {
					this.play(this.playtimes);
				}
				this.playtimes = 0;
				this.goto = -1;
			}
		}

		goto = -1;

		playtimes = 0;

		play(times: number): void {
			if (this.mc) {
				this.mc.play(times);
			} else {
				this.playtimes = times;
				this.goto = -1;
			}
		}

		gotoAndPlay(frame: number, times: number): void {
			if (this.mc) {
				this.mc.gotoAndPlay(frame, times);
			} else {
				this.playtimes = times;
				this.goto = frame;
			}
		}
	}

	export class Click {
		click: egret.MovieClipDataFactory;

		clicktarget: any;

		async CreateClick(target: any): Promise<egret.MovieClip> {
			let Url = '';
			if (!this.click) {
				if (target instanceof game.GameMap) {
					Url = 'ui/common/ani/click1';
				} else {
					Url = 'ui/common/ani/click';
				}
				this.click = await loadMcDataFactoryByUrl(Url);
				if (!this.click) {
					return null;
				}
				this.clicktarget = target;
			}
			if (this.clicktarget !== target) {
				if (target instanceof game.GameMap) {
					Url = 'ui/common/ani/click1';
				} else {
					Url = 'ui/common/ani/click';
				}
				this.click = await loadMcDataFactoryByUrl(Url);
				if (!this.click) {
					return null;
				}
				this.clicktarget = target;
			}
			const mc: egret.MovieClip = new egret.MovieClip(this.click.generateMovieClipData('0'));
			mc.touchEnabled = false;
			return mc;
		}
	}

	let gClick: Click;
	export function getClick(): Click {
		if (!gClick) {
			gClick = new Click();
		}
		return gClick;
	}

	export class Guard {
		guard: egret.MovieClipDataFactory;

		async CreateGuard(): Promise<egret.MovieClip> {
			if (!this.guard) {
				this.guard = await loadMcDataFactoryByUrl('ui/common/finger');
				if (!this.guard) {
					return null;
				}
			}
			const mc: egret.MovieClip = new egret.MovieClip(this.guard.generateMovieClipData('0'));
			mc.touchEnabled = false;
			return mc;
		}
	}

	let gGuard: Guard;
	export function getGuard(): Guard {
		if (!gGuard) {
			gGuard = new Guard();
		}
		return gGuard;
	}

	export class PlaySimpleAni {
		private static instance: PlaySimpleAni;

		public static ins(): PlaySimpleAni {
			if (!this.instance) {
				this.instance = new PlaySimpleAni();
			}
			return this.instance;
		}

		async Play(
			url: string,
			parent: egret.DisplayObjectContainer,
			time = 1,
			x = 0,
			y = 0,
			scaleX = 1,
			scaleY = 1,
			align = 'parent',
			callback?: () => void,
		): Promise<WestMC> {
			const mc = await loadMagicAsyncByUrl('PlaySimpleAni', url);
			if (!mc || !parent) {
				return;
			}
			parent.addChild(mc);
			mc.addEventListener(
				egret.Event.COMPLETE,
				() => {
					parent.removeChild(mc);
					if (callback) {
						callback();
					}
				},
				this,
			);
			mc.play(time);
			const w = align === 'parent' ? parent.width : parent.stage.stageWidth;
			const h = align === 'parent' ? parent.height : parent.stage.stageHeight;
			// console.log(this.parent.width,this.mc.width,this.parent.stage.stageWidth)
			mc.scaleX = scaleX;
			mc.scaleY = scaleY;
			mc.x = w / 2 + x;
			mc.y = h / 2 + y;
			return mc;
		}
	}
}
